package handler

import (
	"database/sql"

	"gitee.com/hp-huiw/family-expense-api/internal/service"
	"github.com/gin-gonic/gin"
)

type FileHandler interface {
	UploadOwnAvatarByBase64(ctx *gin.Context)
	UploadOwnAvatar(ctx *gin.Context)
	UploadAvatar(ctx *gin.Context)
	Upload(ctx *gin.Context)
}

func NewFileHandler(db *sql.DB) FileHandler {
	return &fileHandler{
		fileService: service.NewFileService(db),
	}
}

// Matches /upload-own-avatar-by-base64 of http post action.
func (h *fileHandler) UploadOwnAvatarByBase64(ctx *gin.Context) {
	var postedData struct {
		Filename      string `json:"filename"`
		Base64Content string `json:"base64Content"`
	}

	if err := ctx.ShouldBindJSON(&postedData); err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	claims := GetClaims(ctx)

	// Uploads the avatar file and updates the user avatar info.
	avatarUrl, err := h.fileService.UploadAvatarByBase64(c, claims.UserID, postedData.Filename, postedData.Base64Content)

	if err != nil {
		ctx.Error(err)
		return
	}

	// Sends the avatar url back to client.
	SendDataResponse(ctx, avatarUrl)
}

// Matches /upload-own-avatar of http post action.
func (h *fileHandler) UploadOwnAvatar(ctx *gin.Context) {
	// IMPORTANT: The value of the File method parameter must be the same of the file uploader's html name.
	form, err := ctx.MultipartForm()

	if err != nil {
		ctx.Error(err)
		return
	}

	files := form.File["files[]"]
	claims := GetClaims(ctx)

	// Uploads the avatar file and updates the user avatar info.
	avatarUrl, err := h.fileService.UploadAvatar(claims.UserID, ctx, files[0])

	if err != nil {
		ctx.Error(err)
		return
	}

	// Sends the avatar url back to client.
	SendDataResponse(ctx, avatarUrl)
}

// Matches /upload-avatar of http post action.
func (h *fileHandler) UploadAvatar(ctx *gin.Context) {
	// IMPORTANT: The value of the File method parameter must be the same of the file uploader's html name.
	form, err := ctx.MultipartForm()

	if err != nil {
		ctx.Error(err)
		return
	}

	files := form.File["files[]"]
	userID := ctx.Query("userID")

	// Uploads the avatar file and updates the user avatar info.
	avatarUrl, err := h.fileService.UploadAvatar(userID, ctx, files[0])

	if err != nil {
		ctx.Error(err)
		return
	}

	// Sends the avatar url back to client.
	SendDataResponse(ctx, avatarUrl)
}

// Matches /upload of http post action.
func (h *fileHandler) Upload(ctx *gin.Context) {
	// IMPORTANT: The value of the File method parameter must be the same of the file uploader's html name.
	form, err := ctx.MultipartForm()

	if err != nil {
		ctx.Error(err)
		return
	}

	files := form.File["files"]
	// id := form.Value["id"]

	newFilenames := h.fileService.UploadFiles(ctx, files)

	SendDataResponse(ctx, newFilenames)
}

// Container of RoleHandler functions.
type fileHandler struct {
	fileService service.FileService
}
